﻿using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;

namespace RVBike
{
    public class RVStage
    {
        private const string NAME_TAG = "name";
        private const string DESC_TAG = "description";

        private List<RVMap> _maps;
        private List<RVMovie> _movies;
        private List<RVLanguage> _languages;

        private Dictionary<string, string> _multiTranslate;

        public RVStage(DirectoryInfo di)
        {
            _maps = null;
            _movies = null;
            _languages = null;
            _multiTranslate = new Dictionary<string,string>();

            string pathStageXML = di.FullName + "\\stage.xml";
 
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(pathStageXML);

            XmlElement root = xmlDoc.DocumentElement;
            this.Name = root.GetAttribute("name");
            _multiTranslate[NAME_TAG] = this.Name;
            this.CoverPath = di.FullName + "\\" + root.GetAttribute("cover");
            _multiTranslate[DESC_TAG] = root.GetAttribute("description");

            // check map attributes
            XmlElement mapRoot = (XmlElement)root.SelectSingleNode("/stage/maps");
            string gpsStart = mapRoot.GetAttribute("gps_start");
            string gpsEnd = mapRoot.GetAttribute("gps_end");

            this.GPSStartX = Double.Parse(gpsStart.Substring(0, gpsStart.IndexOf(',')));
            this.GPSStartY = Double.Parse(gpsStart.Substring(gpsStart.IndexOf(',')+1));
            this.GPSEndX = Double.Parse(gpsEnd.Substring(0, gpsEnd.IndexOf(',')));
            this.GPSEndY = Double.Parse(gpsEnd.Substring(gpsEnd.IndexOf(',') + 1));

            XmlNodeList maps = root.SelectNodes("/stage/maps/map");

            _maps = new List<RVMap>();
            for (int index = 0; index < maps.Count; ++index)
            {
                XmlElement map = (XmlElement)maps.Item(index);
                RVMap m = new RVMap();

                m.Level = Int32.Parse(map.GetAttribute("level"));
                m.MapPath = di.FullName + "\\" + map.GetAttribute("file");
                m.LeftMargin = Int32.Parse(map.GetAttribute("left"));
                m.TopMargin = Int32.Parse(map.GetAttribute("top"));
                m.Width = Int32.Parse(map.GetAttribute("width"));
                m.Height = Int32.Parse(map.GetAttribute("height"));

                string mapStart = map.GetAttribute("map_start");
                m.MapStartX = Int32.Parse(mapStart.Substring(0, mapStart.IndexOf(',')));
                m.MapStartY = Int32.Parse(mapStart.Substring(mapStart.IndexOf(',') + 1));

                string mapEnd = map.GetAttribute("map_end");
                m.MapEndX = Int32.Parse(mapEnd.Substring(0, mapEnd.IndexOf(',')));
                m.MapEndY = Int32.Parse(mapEnd.Substring(mapEnd.IndexOf(',') + 1));

                string scale = map.GetAttribute("scale");
                m.ScaleX = Double.Parse(scale.Substring(0, scale.IndexOf(',')));
                m.ScaleY = Double.Parse(scale.Substring(scale.IndexOf(',') + 1));

                _maps.Add(m);
            }

            // check movies elements
            XmlNodeList movies = root.SelectNodes("/stage/movies/movie");

            this.Mileage = 0;
            _movies = new List<RVMovie>();
            for (int index = 0; index < movies.Count; ++index)
            {
                XmlElement movie = (XmlElement)movies.Item(index);
                RVMovie m = new RVMovie();

                m.ID = Int32.Parse(movie.GetAttribute("id"));
                m.VideoPath = di.FullName + "\\" + movie.GetAttribute("file");
                m.Mileage = Int32.Parse(movie.GetAttribute("mileage"));
                this.Mileage += m.Mileage;
                m.MetafilePath = di.FullName + "\\" + movie.GetAttribute("metafile");

                _movies.Add(m);
            }

            // check languages elements
            XmlNodeList languages = root.SelectNodes("/stage/languages/language");

            _languages = new List<RVLanguage>();
            for (int index = 0; index < languages.Count; ++index)
            {
                XmlElement language = (XmlElement)languages.Item(index);
                RVLanguage lang = new RVLanguage();

                lang.Locale = language.GetAttribute("locale");
                lang.StringsPath = di.FullName + "\\" + language.GetAttribute("file");

                _languages.Add(lang);
            }

            // Build multi-language translate string.
            // Read translated string from locle file
            // Find target locale file from language list
            //   - Found : Load string using this file
            //   - Not found : Skip this step to used default string (English)
            RVLanguage targetLocale = null;
            foreach (RVLanguage lan in _languages)
            {
                if (lan.Locale == UserSetting.Instance().Locale)
                {
                    targetLocale = lan;
                }
            }
 
            // Use english
            if (targetLocale != null)
            {
                // Read line by line for $(English_String) = $(Local_String)
                using (StreamReader file = new StreamReader(targetLocale.StringsPath))
                {
                    string line;
                    char[] delimiter = {'='};
                    while ((line = file.ReadLine()) != null)
                    {
                        string[] words = line.Split(delimiter);
                        _multiTranslate[words[0]] = words[1];
                    }
                }
            }
        }

        // Original name in english
        public string Name { get; set; }

        // Name in locale (for display)
        public string DisplayName
        {
            get
            {
                return _multiTranslate[NAME_TAG];
            }
        }

        public string CoverPath { get; set; }
        public string Description
        {
            get
            {
                return _multiTranslate[DESC_TAG];
            }
        }

        public int Mileage { get; set; }

        public double GPSStartX { get; set; }
        public double GPSStartY { get; set; }
        public double GPSEndX { get; set; }
        public double GPSEndY { get; set; }

        public int MovieCount
        {
            get
            {
                return _movies.Count;
            }
        }
        public RVMovie GetMovie(Int32 id)
        {
            RVMovie movie = null;
            foreach (RVMovie m in _movies)
            {
                if (m.ID == id)
                {
                    movie = m;
                    break;
                }
            }
            return movie;
        }

        public int MapCount
        {
            get
            {
                return _maps.Count;
            }
        }
        public RVMap GetMap(Int32 level)
        {
            RVMap map = null;
            foreach (RVMap m in _maps)
            {
                if (m.Level == level)
                {
                    map = m;
                    break;
                }
            }
            return map;
        }

        public int LanguageCount
        {
            get
            {
                return _languages.Count;
            }
        }
        public RVLanguage GetLanguage(String locale)
        {
            RVLanguage lang = null;
            foreach (RVLanguage l in _languages)
            {
                if (l.Locale == locale)
                {
                    lang = l;
                    break;
                }
            }
            return lang;
        }
    }
}
